﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace UserInterface
{

    public delegate void Move(MovingObject check); // Moves the cars in the Crossing
    public delegate void Change(MovingObject check); // Changes crossing to the cars
    
    [Serializable()]
    public abstract class Crossing
    {
        //fields
        protected Point pos;
        public Image im;

        [NonSerialized]
        public PictureBox pbox;
        protected int index;
        public Parent crosType { get; protected set; }
        protected bool run;

        
        /// <summary>
        /// The inner lanes of the crossing, in between named lanes
        /// </summary>
        protected List<Lane> blackboxLanes;
        
        /// <summary>
        /// The lanes tha lead to other crossings or.. nowhere
        /// </summary>
        protected List<Lane> outgoingLanes;

        /// <summary>
        /// List of the crossings that this Crossing can send cars to
        /// </summary>
        protected List<Crossing> myNeighbours;

        /// <summary>
        /// Linked list of traffic lights belonging in the crossing
        /// </summary>
        /// Groups the lights 2gether, according to the method they should light up
        protected LinkedList<TrafficLight>[] myTrafficLight;


        /// <summary>
        /// Linked list of the lanes, grouped on how they should start.
        /// </summary>
        protected LinkedList<Lane>[] myIncomingLanes;


        /// <summary>
        /// The Maximum number of cars in the crossing
        /// </summary>
        protected static int MAXNUMBEROFCARS = 20;

        /// <summary>
        /// Moves the car to the destination lane after exiting the blacbox
        /// </summary>
        /// <param name="mo">The Car move</param>
        public abstract void moveToLane(MovingObject mo); // From Blackbox to a lane
        
        /// <summary>
        /// Changes the initial lane to the blackbox lane
        /// </summar>
        /// <param name="mo">The Car move</param>
        public abstract void moveToBlackbox(MovingObject mo); // Newlly added car, moves to Blackbox
        
        /// <summary>
        /// Passes the car to another neigbhour crossing
        /// </summary>
        /// <param name="mo">The Car transfer</param>
        public abstract void changeToCrossing(MovingObject mo); // Changes the crossing of the car - to a defined lane as well
       
        // public 
        //properties
        /// <summary>
        /// Position of the crossing
        /// </summary>
        public Point Pos
        {
            get;
            protected set;
        }

        //constructors
        /// <summary>
        /// Empty constructor
        /// </summary>
        public Crossing()
        {
        }

        public void mapPicturebox(PictureBox pbx)
        {
            this.pbox = pbx;
            this.pbox.Paint += new PaintEventHandler(getallCars2Draw);
        }
        
        ////methods
        /// <summary>
        /// Returns the number of cars that are currently in the crossing
        /// </summary>
        /// <returns>an integer</returns>
        public int getNumberOfCars() { return 0; }

        /// <summary>
        /// Returns the index of the crossing
        /// </summary>
        /// <returns>an integer</returns>
        public int getIndex() { return index; }
       
        /// <summary>
        /// Moves all the cars in the crossing
        /// </summary>
        public void MoveCars()
        {
            for (int j = 0; j < myIncomingLanes.Length; j++)
            {
                foreach (Lane l in myIncomingLanes[j])
                {
                    l.Move(null, null);
                }
            }

            //for (int i = 0; i < incomingLanes.Count; i++)
             //   incomingLanes[i].MoveCars(null,null);

            for (int i = 0; i < outgoingLanes.Count; i++)
                outgoingLanes[i].Move(null, null);

            for (int i = 0; i < blackboxLanes.Count; i++)
                blackboxLanes[i].Move(null, null);

        }
        /// <summary>
        /// Collects all the points to be drawn
        /// </summary>
        /// <returns>an array of points</returns>
        public abstract void getallCars2Draw(object o,PaintEventArgs e);

        /// <summary>
        /// Main function that does the Job
        /// </summary>
        public abstract void RunMyPattern();

        //public abstract void DrawAll(Graphics gr);

        public abstract Lane PickDeparture();

        public abstract void ResetObjects();

        public abstract void AddNeighbour(ref Crossing c);
        public abstract void GetNeighbour(Crossing c);
        public abstract List<Lane> getPossibleLanes(Direction dir);

        public abstract void GenerateCars();

        public abstract void StopRunning();

        public List<Lane> getLaneStatistics()
        {
            List<Lane> AllLanes = new List<Lane>();
            for (int i = 0; i < myIncomingLanes.Length; i++ )
                foreach (Lane l in myIncomingLanes[i])
                {
                    AllLanes.Add(l);
                }
            foreach (Lane l in blackboxLanes)
                AllLanes.Add(l);
            foreach (Lane l in outgoingLanes)
                AllLanes.Add(l);

                return AllLanes;
        }

        public List<Lane> getLanesToEdit()
        {
            List<Lane> AllLanes = new List<Lane>();
            for (int i = 0; i < myIncomingLanes.Length; i++)
                foreach (Lane l in myIncomingLanes[i])
                {
                    AllLanes.Add(l);
                }
            foreach (Lane l in outgoingLanes)
                AllLanes.Add(l);

            return AllLanes;
        }

        public LinkedList<TrafficLight>[] getTrafficLights()
        {
            return myTrafficLight;
        }

        public abstract List<Pedestrian> getPedestrians();

        public abstract List<PedLane> getPedestrianLanes();
    }
}
